#pragma once
#include <json/json.h>
#include <iostream>
#include <string>
#include "Logger.hpp"
#include <cpr/cpr.h>
#include <elasticlient/client.h>
//封装ES中的数据插入 删除 查找 创建索引四个接口
namespace chatroom{
    class ESindex{
        public:
            ESindex(const std::string& name,const std::string& type,const  std::shared_ptr<elasticlient::Client>& client)
            :_name(name),_type(type),_client(client)
            {
                Json::Value analysis;
                Json::Value analyzer;
                Json::Value ik;
                Json::Value tokenizer;
                tokenizer["tokenizer"] = "ik_max_word";
                ik["ik"] = tokenizer;
                analyzer["analyzer"] = ik;
                analysis["analysis"] = analyzer;
                _index["settings"] = analysis;
            }
            //添加字段
            void append(const std::string& sname,const std::string& stype = "text",const std::string& sanalyzer = "ik_max_word",bool senabled = true)
            {
                Json::Value fileds;
                fileds["type"] = stype;
                fileds["analyzer"] = sanalyzer;
                if(senabled==false) fileds["enabled"] = false;
                _Valuename[sname] = fileds;
            }
            //创建索引
            bool create()
            {
                //1 构建好所有字段
                Json::Value properties;
                properties["properties"] = _Valuename; 
                properties["dynamic"] = true;
                _index["mappings"] = properties;
                //2 进行序列化，发起创建索引请求
                std::string body;
                bool ret = Serialize(_index,body);
                Logger_INFO("请求正文\n{}",body);
                if(ret==false){
                    Logger_INFO("创建索引失败");
                    return false;
                }
                //发起请求
                try{
                    auto rsp = _client->index(_name,_type,"",body);
                    if(rsp.status_code < 200 || rsp.status_code >=300)
                    Logger_ERROR("{}索引创建失败,错误码是{}",_name,rsp.status_code);
                    return false;
                }catch(std::exception& e)
                {
                    Logger_ERROR("{}发生了异常,异常的原因是{}",_name,e.what());
                    return false;
                }
                return true;
            }
        private:
            bool Serialize(const Json::Value& val,std::string& dst)
            {
                Json::StreamWriterBuilder swb;
                std::unique_ptr<Json::StreamWriter> ptr(swb.newStreamWriter());
                std::stringstream str1;
                //调用序列化的接口
                int ret = ptr->write(val,&str1);
                if(ret!=0)
                {
                    std::cout<<"序列化失败"<<std::endl;
                    return false;
                }
                dst = str1.str();
                return true;
            }

            bool UnSerialize(const std::string& str,Json::Value& val)
            {
                Json::CharReaderBuilder crb;
                std::unique_ptr<Json::CharReader> ptr(crb.newCharReader());
                std::string err;
                //调用反序列化的接口
                bool ret = ptr->parse(str.c_str(),str.c_str()+str.size(),&val,&err);
                if(ret == false)
                {
                    std::cout<<"反序列化失败:"<<err<<std::endl;
                    return false;
                }
                return true;
            }
                
        private:
            std::string _name;//索引名称
            std::string _type;//索引类型
            Json::Value _index;//创建的索引
            Json::Value _Valuename;//记录下添加字段的value对象
            std::shared_ptr<elasticlient::Client> _client;
    };
}